using System;
using System.Linq;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using Granite.Collections;

namespace Toon.Models.Catalogs
{
	public interface IChoosable<T>
	{
		T ChooseOne(Random rand);
	}

	public static class Choosable
	{
		public static T ChooseOne<T>(this IChoosable<T> source)
		{
			var rand = new Random();
			return source.ChooseOne(rand);
		}
	}

	public class TableCollection<T> : Collection<Table<T>>, IChoosable<T>
	{
		public TableCollection(IEnumerable<Table<T>> tables)
			: base(tables.ToList())
		{

		}

		public TableCollection(params Table<T>[] tables)
			: base(tables)
		{

		}

		public Table<T> ChooseTable(Random rand)
		{
			return rand.ChooseOne(this);
		}

		public T ChooseOne(Random rand)
		{
			return ChooseTable(rand).ChooseOne(rand);
		}
	}

	public class TableCollectionBuilder<T>
	{
		readonly List<TableBuilder<T>> m_Tables = new List<TableBuilder<T>>();

		public TableCollection<T> ToTableCollection()
		{
			return new TableCollection<T>(m_Tables.Select(t => t.ToTable()));
		}

		public TableBuilder<T> this[string tableName]
		{
			get
			{
				if (Contains(tableName))
					return m_Tables.Single(t => t.TableName == tableName);
				else
				{
					var temp = new TableBuilder<T>(tableName);
					m_Tables.Add(temp);
					return temp;
				}
			}
		}

		private bool Contains(string tableName)
		{
			return m_Tables.Any(t => t.TableName == tableName);
		}


	}

	public class TableBuilder<T> : Collection<TableItem<T>>
	{
		public string TableName { get; set; }

		public TableBuilder(string tableName)
		{
			TableName = tableName;
		}

		public Table<T> ToTable()
		{
			return new Table<T>(TableName, this);
		}

		public void Add(T item, int frequency = 1)
		{
			Add(new TableItem<T>(item, frequency));
		}

		public void AddRange(params T[] items)
		{
			foreach (var item in items)
				Add(item);
		}
	}

}
